package com.jiot.common;

import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.tio.websocket.common.WsResponse;

import com.jfinal.aop.AopManager;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.plugin.redis.RedisPlugin;
import com.jfinal.plugin.redis.serializer.JdkSerializer;
import com.jfinal.server.undertow.UndertowServer;
import com.jfinal.template.Engine;
import com.jfinal.weixin.sdk.api.ApiConfig;
import com.jfinal.weixin.sdk.api.ApiConfigKit;
import com.jfinal.wxaapp.WxaConfig;
import com.jfinal.wxaapp.WxaConfigKit;
import com.jiot.common.constant.CacheConstant;
import com.jiot.common.model._MappingKit;
import com.jiot.common.routes.FrontRoutes;
import com.jiot.plugin.HikariCP.HikariCPPlugin;
import com.jiot.plugin.influx.InFluxDbPlugin;
import com.jiot.plugin.motan.client.MyAopFactory;
import com.jiot.plugin.motan.export.ExportPlugin;
import com.jiot.plugin.mqtt.MqttHandler;
import com.jiot.plugin.mqtt.MqttKit;
import com.jiot.plugin.mqtt.MqttPlugin;
import com.jiot.plugin.qiniu.QiniuPlugin;
import com.jiot.plugin.tio.MyWsMsgHandler;
import com.jiot.plugin.tio.TioWebsocketStarterPlugin;
import com.jiot.plugin.xxljob.xxlJobPlugin;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

/**
 * API 引导式配置
 */
public class jiotConfig extends JFinalConfig {

	static Prop p;

	/**
	 * 启动入口，运行此 main 方法可以启动项目，此 main 方法可以放置在任意的 Class 类定义中，不一定要放于此
	 */
	public static void main(String[] args) {
		System.setProperty("org.eclipse.jetty.server.Request.maxFormContentSize", "-1");
		UndertowServer.start(jiotConfig.class);
	}

	/**
	 * PropKit.useFirstFound(...) 使用参数中从左到右最先被找到的配置文件
	 * 从左到右依次去找配置，找到则立即加载并立即返回，后续配置将被忽略
	 */
	static void loadConfig() {
		if (p == null) {
			p = PropKit.useFirstFound("demo-config-pro.txt", "demo-config-dev.txt");
		}
	}

	/**
	 * 配置常量
	 */
	public void configConstant(Constants me) {
		loadConfig();

		me.setDevMode(p.getBoolean("devMode", false));
		me.setMaxPostSize(10000000);
		/**
		 * 支持 Controller、Interceptor、Validator 之中使用 @Inject 注入业务层，并且自动实现 AOP
		 * 注入动作支持任意深度并自动处理循环注入
		 */
		me.setInjectDependency(true);

		// 配置对超类中的属性进行注入
		me.setInjectSuperClass(true);

		// 覆盖AopFactory中的方法,当前添加了MyRPC注入
		AopManager.me().setAopFactory(new MyAopFactory());
	}

	/**
	 * 配置路由
	 */
	public void configRoute(Routes me) {
		// me.add("/", IndexController.class, "/index"); // 第三个参数为该Controller的视图存放路径
		me.add(new FrontRoutes());
		// me.add("/login", loginController.class); // 第三个参数省略时默认与第一个参数值相同，在此即为 "/blog"
//		me.scan("com.riji.controller.");
	}

	public void configEngine(Engine me) {
//		me.addSharedFunction("/common/_layout.html");
//		me.addSharedFunction("/common/_paginate.html");
	}

	/**
	 * 配置插件
	 */
	public void configPlugin(Plugins me) {
		// 配置 druid 数据库连接池插件
//		DruidPlugin dbPool = new DruidPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password").trim());
//		me.add(dbPool);
//		HikariCPPlugin dbPool = new HikariCPPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password").trim(), p.get("driverClassName").trim());
//		me.add(dbPool);

		// 配置ActiveRecord插件
//		ActiveRecordPlugin arp = new ActiveRecordPlugin(dbPool);
//		arp.addSqlTemplate("all.sql");// sql模板
		// 所有映射在 MappingKit 中自动化搞定
//		_MappingKit.mapping(arp);
//		me.add(arp);
		// 配置EhCachePlugin插件
		me.add(new EhCachePlugin());
		// redis
		RedisPlugin redisPlugin = new RedisPlugin(CacheConstant.appUser, "127.0.0.1");
		redisPlugin.setSerializer(JdkSerializer.me); // 需要使用fst高性能序列化的用户请删除这一行（Fst jar依赖请查看WIKI）
		me.add(redisPlugin);
//        RedisPlugin unionidRedis = new RedisPlugin("unionidANDid", "127.0.0.1");
//        unionidRedis.setSerializer(JdkSerializer.me);
//        me.add(unionidRedis);
		//influxdb
		me.add(new InFluxDbPlugin("influxDb.properties"));
		// mqtt
		me.add(new MqttPlugin("mqtt.properties"));
		// qiniu
//		me.add(new QiniuPlugin("qiniu.properties"));
		// tio
		me.add(new TioWebsocketStarterPlugin("tio.properties"));
		// Motan-rpc
//		me.add(new ExportPlugin("rpc.properties"));
		// xxl-job
//		me.add(new xxlJobPlugin("xxl-job-executor.properties"));
		
	}

	public static DruidPlugin createDruidPlugin() {
		loadConfig();

		return new DruidPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password").trim());
	}

	/**
	 * 配置全局拦截器它只拦截action请求，对静态资源比如css,image等是不拦截的
	 */
	public void configInterceptor(Interceptors me) {
//		me.addGlobalActionInterceptor(new GlobalExceptionInterceptor());
	}

	/**
	 * 配置处理器,像servlet中的Filter拦截一切请求响应，不管是action请求，还是访问静态资源都会进行拦截，并且可以对拦截的参数，进行重写，重写URL
	 */
	public void configHandler(Handlers me) {

	}

	// 系统启动完成后回调
	public void onStart() {
//		initWX();
		MqttHandler mqttHandler = new MqttHandler();
		mqttHandler.mqtt();
		
	}

	// 系统关闭之前回调
	public void onStop() {
		try {
			//取消订阅
			MqttKit.unsub("/hello");
		} catch (MqttException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	public void initWX() {
		// 1.5 之后支持redis存储access_token、js_ticket，需要先启动RedisPlugin
//      ApiConfigKit.setAccessTokenCache(new RedisAccessTokenCache());
		// 1.6新增的2种初始化
//      ApiConfigKit.setAccessTokenCache(new RedisAccessTokenCache(Redis.use("weixin")));
//      ApiConfigKit.setAccessTokenCache(new RedisAccessTokenCache("weixin"));

		ApiConfig ac = new ApiConfig();
		// 配置微信 API 相关参数
		ac.setToken(PropKit.get("token"));
		ac.setAppId(PropKit.get("appId"));
		ac.setAppSecret(PropKit.get("appSecret"));

		/**
		 * 是否对消息进行加密，对应于微信平台的消息加解密方式： 1：true进行加密且必须配置 encodingAesKey
		 * 2：false采用明文模式，同时也支持混合模式
		 */
		ac.setEncryptMessage(PropKit.getBoolean("encryptMessage", false));
		ac.setEncodingAesKey(PropKit.get("encodingAesKey", "setting it in config file"));

		/**
		 * 多个公众号时，重复调用ApiConfigKit.putApiConfig(ac)依次添加即可，第一个添加的是默认。
		 */
		ApiConfigKit.putApiConfig(ac);

		/**
		 * 1.9 新增LocalTestTokenCache用于本地和线上同时使用一套appId时避免本地将线上AccessToken冲掉
		 * 
		 * 设计初衷：https://www.oschina.net/question/2702126_2237352
		 * 
		 * 注意： 1. 上线时应保证此处isLocalDev为false，或者注释掉该不分代码！
		 * 
		 * 2. 为了安全起见，此处可以自己添加密钥之类的参数，例如：
		 * http://localhost/weixin/api/getToken?secret=xxxx
		 * 然后在WeixinApiController#getToken()方法中判断secret
		 * 
		 * @see WeixinApiController#getToken()
		 */
//      if (isLocalDev) {
//          String onLineTokenUrl = "http://localhost/weixin/api/getToken";
//          ApiConfigKit.setAccessTokenCache(new LocalTestTokenCache(onLineTokenUrl));
//      }
		WxaConfig wc = new WxaConfig();
		wc.setAppId("wx4f53594f9a6b3dcb");
		wc.setAppSecret("eec6482ba3804df05bd10895bace0579");
		WxaConfigKit.setWxaConfig(wc);
	}

}
